package jMiiEditor.mii.checker;

import jMiiEditor.mii.Mii;
import java.util.ArrayList;
import java.util.List;
import utils.BinStuffs;

public class MiiChecker
{
    private Mii mii;
    private List<MiiCheckerProposal> miiCheckerResultCollection = new ArrayList<MiiCheckerProposal>();

    public MiiChecker( Mii mii )
    {
        this.mii = mii;
    }

    public List<MiiCheckerProposal> getMiiCheckerResults()
    {
        return miiCheckerResultCollection;
    }
    
    public MiiCheckerResult apply( 
            MiiCheckerFileObject aFileObject
            ) 
        //throws MiiCheckerActionException
    {
        return apply( this.miiCheckerResultCollection, aFileObject, this.mii);
    }
    
    public static MiiCheckerResult apply( 
            List<MiiCheckerProposal> miiCheckerResultToApplyList,
            MiiCheckerFileObject   aFileObject, 
            Mii                    aMii 
            ) 
        //throws MiiCheckerActionException
    {
        MiiCheckerResult result = new MiiCheckerResult();

        result.setMii( aMii );
        result.setMiiCheckerFileObject( aFileObject );
        
        for( MiiCheckerProposal entry : miiCheckerResultToApplyList) {
            if( entry instanceof MiiCheckerProposalAction) {
                try {
                    MiiCheckerProposalAction.class.cast( entry ).applyOn( result );
                }
                catch( MiiCheckerActionException e ) {
                    result.addException( entry, e );
                }
            }
        }
        
        return result;
    }

    public void performAllChecks( MiiCheckerDefault defaultValues )
    {
        basicChecks();
        checkFilename( defaultValues.getFileName() );
        checkSystemId( defaultValues.getSystemId() );
        
        int countAction = 0;

        for( MiiCheckerProposal entry : miiCheckerResultCollection) {
            if( entry instanceof MiiCheckerProposalAction ) {
                countAction++;
            }
        }
        
        if( countAction > 0 ) {
            miiCheckerResultCollection.add( 
                    new MiiCheckerProposalSaveAction( "Save modifications" ) 
                    );
        }
    }

    private MiiChecker basicChecks()
    {
        if( mii.isInvalid() ) {
            addMiiAction(
                    "Mii is define has invalid",
                    true,
                    "setInvalid",
                    false
               );
        }

        if( mii.getMonth() == 0 && mii.getDay() != 0 ) {
            addMiiAction(
                    "Month is not set, but Day has a value",
                    false,
                    "setDay",
                    0
                    );
        }

        if( mii.getMonth() != 0 && mii.getDay() == 0 ) {
            addMiiAction(
                    "Day is not set, but Month has a value",
                    false,
                    "setMonth",
                    0
                    );
        }

        byte[] miiId = mii.getMiiId();
        int    miiIdType = miiId[ 0 ] & 0x00F0;

        if( miiIdType < 0x20 ) {
            addInfo( "Special Mii - Gold Pants [" + BinStuffs.ubyteToHexString( miiIdType ) + "]" );
        }
        else if( miiIdType < 0x40 ) {
            addInfo( "Normal Mii - Black Pants [" + BinStuffs.ubyteToHexString( miiIdType ) + "]" );
        }
        else if( miiIdType < 0x60 ) {
            addInfo( "Special Mii - Gold Pants [" + BinStuffs.ubyteToHexString( miiIdType ) + "]" );
        }
        else if( miiIdType < 0xC0 ) {
            addInfo( "Normal Mii - Black Pants [" + BinStuffs.ubyteToHexString( miiIdType ) + "]" );
        }
        else if( miiIdType < 0xE0 ) {
            byte[] bytes = new byte[ miiId.length ];

            for( int i=0; i<miiId.length; i++ ) {
                bytes[i] = miiId[i];
            }
            bytes[0] &= 0x0F; // remove type info
            bytes[0] |= 0x40; // set to normal mii

            addMiiAction(
                    "Foreign Mii - Blue Pants (uneditable)",
                    false,
                    "setMiiId",
                    bytes
                    );
        }
        else {
            addInfo( "Normal Mii - Black Pants [" + BinStuffs.ubyteToHexString( miiIdType ) + "]" );
        }

        if( mii.isUnknown$0x30$00000001() ) {
            addMiiAction(
                    "Your Mii does not appear (use not known)",
                    true,
                    "setUnknown$0x30$00000001",
                    false
                    );
        }

        return this;
    }

    private MiiChecker checkFilename( String filename )
    {
        if( filename == null ) {
            addInfo( "No file." );
        }
        else {
            String miiName = mii.getMiiName().trim();
            
            if( !filename.contains( miiName ) ) {
                addFileAction(
                    "Filename [" + filename + "] doesn't contain miiName.",
                    miiName + ".mii"
                    );
            }
        }

        return this;
    }

    private MiiChecker checkSystemId( byte[] systemId )
    {
        if( systemId == null || systemId.length != 4 ) {
            addInfo( "You should define a defaut SystemId for be able to edit this mii" );
        }
        else {
            byte[] miiSystemId = mii.getSystemId();
            boolean eq = true;

            for(int i=0;i<miiSystemId.length;i++) {
                if( systemId[i] != miiSystemId[i]) {
                    eq = false;
                }
            }

            if( !eq ) {
                addMiiAction(
                        "set SystemId to your Wii SystemId",
                        true,
                        "setSystemId",
                        systemId
                        );
            }
        }

        return this;
    }

    private void addInfo( String message )
    {
        miiCheckerResultCollection.add( new MiiCheckerProposalInfo( message ) );
    }

    private void addMiiAction( String message, boolean isSelected, String  miiMethodName, boolean miiMethodParam )
    {
        miiCheckerResultCollection.add( new MiiCheckerProposalMiiAction( message, isSelected, miiMethodName, miiMethodParam ) );
    }

    private void addMiiAction( String message, boolean isSelected, String  miiMethodName, int miiMethodParam )
    {
        miiCheckerResultCollection.add( new MiiCheckerProposalMiiAction( message, isSelected, miiMethodName, miiMethodParam ) );
    }

    private void addMiiAction( String message, boolean isSelected, String  miiMethodName, byte[] miiMethodParam )
    {
        miiCheckerResultCollection.add( new MiiCheckerProposalMiiAction( message, isSelected, miiMethodName, miiMethodParam ) );
    }

    private void addFileAction( String message, String newName )
    {
        miiCheckerResultCollection.add( new MiiCheckerProposalRenameAction( message, newName ) );
    }
}
